// --------------------------------------------------------------------------
// Copyright (c) MEMOS Software s.r.o. All rights reserved.
//
// Outlook Bar Demonstration
// 
// File     : MyPanel.cs
// Author   : Lukas Neumann <lukas.neumann@memos.cz>
// Created  : 080622
//
// -------------------------------------------------------------------------- 

using System;
using System.Diagnostics;
using System.Drawing;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

using System.Globalization;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using Microsoft.Office.Interop.Outlook;
using System.Collections.Generic;
using Exception = System.Exception;
using System.Windows.Forms.Integration;
using Visifire.Charts;
using System.Threading;
using System.Linq;
using SNAIL.Classes;

using Facebook.Schema;
using Facebook.Winforms;

using CookComputing.XmlRpc;

namespace OutlookPanel
{
    /// <summary>
    /// Custom docked panel control
    /// </summary>
    /// <remarks>
    /// This panel shows subject and all recipients of the email which is selected.
    /// </remarks>
    /// 
    public enum SortingSetting
    {
        ConceptWu,
        ConceptWieth,
        ConceptDefault
    }

    [XmlRpcUrl("http://localhost:8001/ThunderbirdMessage")]
    public interface ISNAILXMLRPC : IXmlRpcProxy
    {
        [XmlRpcMethod("ThunderbirdMessage.eventViewEmail")]
        string eventViewEmail(XmlRpcStruct input);

        //WIRED UP
        [XmlRpcMethod("ThunderbirdMessage.eventEmailSelected")]
        string eventEmailSelected(XmlRpcStruct input);

        [XmlRpcMethod("ThunderbirdMessage.eventDeleteEmail")]
        string eventDeleteEmail(XmlRpcStruct input);

        //WIRED UP
        [XmlRpcMethod("ThunderbirdMessage.eventSendEmail")]
        string eventSendEmail(XmlRpcStruct input);

        //WIRED UP
        [XmlRpcMethod("ThunderbirdMessage.eventFolderSelected")]
        string eventFolderSelected(XmlRpcStruct input);

        [XmlRpcMethod("ThunderbirdMessage.eventAddFolder")]
        string eventAddFolder(XmlRpcStruct input);

        [XmlRpcMethod("ThunderbirdMessage.eventRenameFolder")]
        string eventRenameFolder(XmlRpcStruct input);

        [XmlRpcMethod("ThunderbirdMessage.eventDeleteFolder")]
        string eventDeleteFolder(XmlRpcStruct input);

        [XmlRpcMethod("ThunderbirdMessage.eventMoveEmailToFolder")]
        string eventMoveEmailToFolder(XmlRpcStruct input);

        [XmlRpcMethod("ThunderbirdMessage.eventReceiveEmail")]
        string eventReceiveEmail(XmlRpcStruct input);

        [XmlRpcMethod("ThunderbirdMessage.eventForwardEmail")]
        string eventForwardEmail(XmlRpcStruct input);

        [XmlRpcMethod("ThunderbirdMessage.eventReplyToEmail")]
        string eventReplyToEmail(XmlRpcStruct input);

        [XmlRpcMethod("ThunderbirdMessage.eventPrintEmail")]
        string eventPrintEmail(XmlRpcStruct input);

        [XmlRpcMethod("ThunderbirdMessage.eventAddAddressBookEntry")]
        string eventAddAddressBookEntry(XmlRpcStruct input);

        [XmlRpcMethod("ThunderbirdMessage.eventModifyAddressBookEntry")]
        string eventModifyAddressBookEntry(XmlRpcStruct input);

        [XmlRpcMethod("ThunderbirdMessage.eventDeleteAddressBookEntry")]
        string eventDeleteAddressBookEntry(XmlRpcStruct input);
    }

    public partial class MyPanel : UserControl
    {
        /// <summary>
        /// Default constructor
        /// </summary>
        public MyPanel(Microsoft.Office.Interop.Outlook.Application app)
        {
            outlookapp = app;
            outlookapp.ItemSend += new ApplicationEvents_11_ItemSendEventHandler(outlookapp_ItemSend);
            outlookapp.NewMail += new ApplicationEvents_11_NewMailEventHandler(outlookapp_NewMail);
            outlookapp.ActiveExplorer().SelectionChange += new ExplorerEvents_10_SelectionChangeEventHandler(MyPanel_SelectionChange);
            
            InitializeComponent();
            listBox1 = ((SNAIL.UserControl2)elementHost1.Child).PersonList;
            listBox1.MouseDoubleClick += new System.Windows.Input.MouseButtonEventHandler(listBox1_MouseDoubleClick);
        }

        void MyPanel_SelectionChange()
        {
            if (outlookapp.ActiveExplorer().Selection.Count == 0)
                return; //No selection has been made

            //Take the first selected item 
            MailItem mailItem = outlookapp.ActiveExplorer().Selection[1] as MailItem;

            if (mailItem != null)
            {
                XMLRPCPROXY.eventEmailSelected(new XmlRpcStruct());
            }
            else
            {
                //Take the first selected item 
                Folder FolderItem = outlookapp.ActiveExplorer().Selection[1] as Folder;

                if (FolderItem != null)
                {
                    XMLRPCPROXY.eventFolderSelected(new XmlRpcStruct());
                }
            }

        }

        void outlookapp_ItemSend(object Item, ref bool Cancel)
        {
            XMLRPCPROXY.eventSendEmail(new XmlRpcStruct());
        }

        ISNAILXMLRPC XMLRPCPROXY = XmlRpcProxyGen.Create<ISNAILXMLRPC>();

        void outlookapp_NewMail()
        {
            XMLRPCPROXY.eventReceiveEmail(new XmlRpcStruct());
            GetUnreadMail();
        }

        /// <summary>
        /// Returns if specified text is an email address
        /// </summary>
        /// <param name="text"></param>
        /// <returns></returns>
        private static bool IsEmailAddress(string text)
        {
            return new Regex(@"^[A-Z0-9._%-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$", RegexOptions.IgnoreCase).IsMatch(text);
        }

        /// <summary>
        /// Search for specified person
        /// </summary>
        /// <param name="personName"></param>
        private static void SearchForPerson(string personName)
        {
            if (String.IsNullOrEmpty(personName))
                return; //Do not search for empty people

            //Search the person using Google
            string url = Uri.EscapeUriString(String.Format(CultureInfo.InvariantCulture, "http://www.google.cz/search?q={0}", personName));

            try
            {
                //Display the url using default web browser
                Process.Start(url);
            }
            catch (Exception ex)
            {
                //An error occured
                Trace.Write(ex.ToString());
                MessageBox.Show(String.Format(CultureInfo.CurrentCulture, "Cannot navigate to {0}.\r\n{1}", url, ex.Message));

            }
        }

        Items ContactFolderItems;

        private void SubscribeToEvents()
        {
            foreach (Folder folder in GetAllSubFolders((Folder)outlookapp.Session.GetDefaultFolder(Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderInbox)))
            {
                Items UnreadItem = folder.Items;
                UnreadItem.ItemChange += new ItemsEvents_ItemChangeEventHandler(UnreadItems_ItemChange);
                UnreadItems.Add(UnreadItem);
            }
            ContactFolderItems = outlookapp.Session.GetDefaultFolder(OlDefaultFolders.olFolderContacts).Items;
            ContactFolderItems.ItemChange += new ItemsEvents_ItemChangeEventHandler(Contacts_ItemChange);
            ContactFolderItems.ItemAdd += new ItemsEvents_ItemAddEventHandler(ContactFolderItems_ItemAdd);
            ContactFolderItems.ItemRemove += new ItemsEvents_ItemRemoveEventHandler(ContactFolderItems_ItemRemove);
        }

        void ContactFolderItems_ItemRemove()
        {
            RefreshList();
        }

        void ContactFolderItems_ItemAdd(object Item)
        {
            RefreshList();
        }

        void Contacts_ItemChange(object Item)
        {
            RefreshList();
        }

        List<Items> UnreadItems = new List<Items>();

        private void GetUnreadMail()
        {
            foreach (Folder folder in GetAllSubFolders((Folder)outlookapp.Session.GetDefaultFolder(Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderInbox)))
            {
                Items unreadMailItems = folder.Items.Restrict("[Unread]= true");
                //UnreadItems = unreadMailItems;
                //UnreadItems.ItemChange += new ItemsEvents_ItemChangeEventHandler(UnreadItems_ItemChange);
                foreach (var Item in unreadMailItems)
                {
                    try
                    {
                        MailItem mi = Item as MailItem;
                        Contact TempContact = new Contact(mi);

                        if (!FromToMessages.ContainsKey(TempContact))
                        {
                            List<string> Tempmessage = new List<string>();
                            FromToMessages.Add(TempContact, new ContactMessages(new List<ContactMessage> { new ContactMessage(mi.EntryID, mi.SentOn) }, new List<ContactMessage>()));
                        }
                        else
                        {
                            if (!FromToMessages[TempContact].FromMessages.Contains(new ContactMessage(mi.EntryID)))
                            {
                                FromToMessages[TempContact].FromMessages.Add(new ContactMessage(mi.EntryID, mi.SentOn));
                            }
                        }

                        Contact TempCont = Contacts.Find(
                            delegate(Contact c)
                            {
                                Contact UnreadContact = new Contact(mi);
                                return c.Equals(UnreadContact);
                            });

                        if (TempCont.UnreadMailsList == null)
                        {
                            TempCont.UnreadMailsList = new List<MailItem> { mi };
                        }
                        else
                        {
                            TempCont.UnreadMailsList.Add(mi);
                        }
                        TempCont.UnreadMails = mi.UnRead;
                    }
                    catch
                    {
                    }
                }
            }

            RefreshList();
        }

        void UnreadItems_ItemChange(object Item)
        {
            try
            {
                MailItem mi = Item as MailItem;

                Contact ChangedContact = new Contact(mi);

                if (FromToMessages.ContainsKey(ChangedContact))
                {
                    ChangedContact = Contacts.Find(
                    delegate(Contact c)
                    {
                        Contact UnreadContact = new Contact(mi);
                        return c.Equals(UnreadContact);
                    });


                    ChangedContact.UnreadMails = mi.UnRead;

                    if (mi.UnRead)
                    {
                        if (ChangedContact.UnreadMailsList == null)
                        {
                            ChangedContact.UnreadMailsList = new List<MailItem> { mi };
                        }
                        else
                        {
                            if (!ChangedContact.UnreadMailsList.Contains(mi))
                            {
                                ChangedContact.UnreadMailsList.Add(mi);
                            }
                        }
                    }
                    else
                    {
                        if (ChangedContact.UnreadMailsList != null)
                        {
                            if (ChangedContact.UnreadMailsList.Contains(mi))
                            {
                                ChangedContact.UnreadMailsList.Remove(mi);
                            }
                        }
                    }
                }
                else
                {
                    ChangedContact.UnreadMails = mi.UnRead;

                    if (mi.UnRead)
                    {
                        if (ChangedContact.UnreadMailsList == null)
                        {
                            ChangedContact.UnreadMailsList = new List<MailItem> { mi };
                        }
                        else
                        {
                            if (!ChangedContact.UnreadMailsList.Contains(mi))
                            {
                                ChangedContact.UnreadMailsList.Add(mi);
                            }
                        }
                    }

                    else
                    {
                        ChangedContact.UnreadMails = mi.UnRead;

                        if (ChangedContact.UnreadMailsList != null)
                        {
                            if (ChangedContact.UnreadMailsList.Contains(mi))
                            {
                                ChangedContact.UnreadMailsList.Remove(mi);
                            }
                        }
                    }
                    FromToMessages.Add(ChangedContact, new ContactMessages(new List<ContactMessage> { new ContactMessage(mi.EntryID, mi.SentOn) }, new List<ContactMessage>()));
                }

                RefreshList();
            }
            catch
            {
            }
        }

        /// <summary>
        /// Refreshes and resorts the list
        /// This is the place to change sorting behaviour
        /// </summary>
        public void RefreshList()
        {
            foreach (Contact contact in Contacts)
            {
                if (contact.OutlookContact != null)
                {
                    try
                    {
                        contact.ContactImagePath = Contact.GetContactPicturePath((ContactItem)outlookapp.Session.GetItemFromID(contact.OutlookContact, null));
                    }
                    catch (System.Runtime.InteropServices.COMException ex)
                    {
                        //Element nicht gefunden
                        contact.ContactImagePath = null;
                        contact.OutlookContact = null;
                    }
                    catch (Exception)
                    {
                    }
                }
                else if (contact.FacebookUID != null)
                {
                    try
                    {
                        contact.ContactImagePath = facebookService1.Users.GetInfo(contact.FacebookUID.Value).pic;
                    }
                    catch (Exception)
                    {
                    }
                }
            }

            if (SortSetting == SortingSetting.ConceptWu)
            {
                //CONCEPT WU: RATING BASED
                //AKA CONCEPT ROX
                Contacts = Contacts.OrderByDescending(x => x.UnreadMails).ThenBy(x => x.RatingsScore).ToList();
            }
            else if (SortSetting == SortingSetting.ConceptWieth)
            {
                //CONCEPT WIETH: LAST MESSAGE & SENT MESSAGES
                //AKA CONCEPT SUX
                Contacts = Contacts.OrderByDescending(x => x.UnreadMails).ThenByDescending(x => x.LastMessageSent).ThenByDescending(x => x.SentToCount).ToList();

                //Contacts = Contacts.OrderByDescending(x => x.UnreadMails).ThenByDescending(x => x.LastMessageSent > (DateTime.Today - TimeSpan.FromDays(DaysForCorrelation))).ThenBy(x => x.RatingsScore).ToList();

            }
            else if (SortSetting == SortingSetting.ConceptDefault)
            {
                Contacts = Contacts.OrderByDescending(x => x.UnreadMails).ThenBy(
                   x =>
                       (Math.Abs(1.0 - ((Convert.ToDouble(FromToMessages[x].ToMessages.Count(y => y.MailDate > (DateTime.Today - TimeSpan.FromDays(DaysForCorrelation)))) + 0.00001) / (Convert.ToDouble(FromToMessages[x].FromMessages.Count(y => y.MailDate > (DateTime.Today - TimeSpan.FromDays(DaysForCorrelation)))) + 0.00001))) + 0.1) / (FromToMessages[x].ToMessages.Count(y => y.MailDate > (DateTime.Today - TimeSpan.FromDays(DaysForCorrelation))) + 0.00001)
                       ).ThenBy(x => x.RatingsScore).ToList();
                //Contacts = Contacts.OrderByDescending(x => x.UnreadMails).ThenByDescending(x => x.ReceivedFromCount).ToList();
            }
            listBox1.ItemsSource = Contacts;
            listBox1.Items.Refresh();
        }

        public int DaysForCorrelation = 30;

        public SortingSetting SortSetting = SortingSetting.ConceptDefault;

        /// <summary>
        /// Control load event handler
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void DockedControl_Load(object sender, EventArgs e)
        {
            this.BackColor = Color.White;
            //GenerateDel gen = new GenerateDel(GenerateStatistics);
            //gen.BeginInvoke(null, null);

            if (!Directory.Exists(Path.GetDirectoryName(fileName)))
            {
                Directory.CreateDirectory(Path.GetDirectoryName(fileName));
            }

            outlookapp.Startup += new ApplicationEvents_11_StartupEventHandler(outlookapp_Startup);

            //SNAILStartup();

            // mainsyncobject = outlookapp.Session.SyncObjects[0];
            // mainsyncobject.SyncEnd += new SyncObjectEvents_SyncEndEventHandler(syncobject_SyncEnd);
        }

        void outlookapp_Startup()
        {
            SNAILStartup();
        }

        void syncobject_SyncEnd()
        {
            SNAILStartup();
        }

        void SNAILStartup()
        {
            if (File.Exists(fileName))
            {
                try
                {
                    Stream stream = File.Open(fileName, FileMode.Open);
                    BinaryFormatter bFormatter = new BinaryFormatter();
                    try
                    {
                        FromToMessages = (Dictionary<Contact, ContactMessages>)bFormatter.Deserialize(stream);
                    }
                    catch (Exception)
                    {

                        throw;
                    }
                    finally
                    {
                        stream.Close();
                    }
                }
                catch
                {
                    GenerateStatistics();
                }
            }
            else
            {
                GenerateStatistics();
            }

            foreach (var item in FromToMessages.Keys)
            {
                item.ReceivedFromCount = FromToMessages[item].FromMessages.Count;
                item.SentToCount = FromToMessages[item].ToMessages.Count;
                // listBox1.Items.Add(item);
            }

            Contacts = new List<Contact>(FromToMessages.Keys);

            //Contacts.Sort(delegate(Contact c1, Contact c2)
            //{
            //    return c2.ReceivedFromCount.CompareTo(c1.ReceivedFromCount);
            //});

            GetUnreadMail();


            //Contacts.Sort(delegate(Contact c1, Contact c2)
            //{
            //    return c2.UnreadMails.CompareTo(c1.UnreadMails);
            //});

            facebookService1.ConnectToFacebook(new List<Enums.ExtendedPermissions>() { Enums.ExtendedPermissions.read_stream, Enums.ExtendedPermissions.publish_stream });

            RefreshList();

            SubscribeToEvents();
        }

        void listBox1_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            ContactAction();
        }

        /// <summary>
        /// Calculates the Ratings for a given list of Contacts
        /// </summary>
        /// <param name="Contacts"></param>
        private void CalculateRatings(List<Contact> Contacts)
        {
            foreach (Contact contact in Contacts)
            {
                //OUT/IN Rating, higher values means we send more than we receive
                //which is good
                double rating = contact.SentToCount / contact.ReceivedFromCount;

            }
        }

        private System.Windows.Controls.ListBox listBox1;

        string fileName = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), Path.Combine("SNAIL", "SNAIL_DICT.dict"));

        public delegate void GenerateDel();

        private Microsoft.Office.Interop.Outlook.Application outlookapp;

        public List<Contact> Contacts;

        /// <summary>
        /// User moves cursor above the people control
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void lstRecipients_MouseMove(object sender, MouseEventArgs e)
        {
            ////If there is an item under the cursor, show the hand cursor
            //this.lstRecipients.Cursor = lstRecipients.IndexFromPoint(e.Location) >= 0 ? Cursors.Hand : Cursors.Default;
        }

        // KEY: CONTACT, VALUE: MESSAGE STASH
        public Dictionary<Contact, ContactMessages> FromToMessages = new Dictionary<Contact, ContactMessages>();


        private delegate object DElGetoFolder();

        private Items GetInboxItems()
        {
            if (this.InvokeRequired)
            {
                return (Items)this.Invoke(new DElGetoFolder(GetInboxItems));
            }
            else
            {
                return outlookapp.Session.GetDefaultFolder(Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderInbox).Items;
            }
        }

        private List<MailItem> GetAllItemsRecursion(MAPIFolder ProcessingFolder, List<MailItem> Items)
        {
            foreach (var item in ProcessingFolder.Items)
            {
                try
                {
                    MailItem mi = item as MailItem;
                    Items.Add(mi);
                }
                catch (Exception)
                {
                }
            }
            foreach (Folder childfolder in ProcessingFolder.Folders)
            {
                GetAllItemsRecursion(childfolder, Items);
            }
            return Items;
        }

        private Items GetAllItems()
        {
            if (this.InvokeRequired)
            {
                return (Items)this.Invoke(new DElGetoFolder(GetAllItems));
            }
            else
            {
                return outlookapp.Session.GetDefaultFolder(Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderInbox).Items;
            }
        }

        private Items GetSentItems()
        {
            if (this.InvokeRequired)
            {
                return (Items)this.Invoke(new DElGetoFolder(GetSentItems));
            }
            else
            {
                return outlookapp.Session.GetDefaultFolder(Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderSentMail).Items;
            }
        }

        private Folders GetInboxFolders()
        {
            if (this.InvokeRequired)
            {
                return (Folders)this.Invoke(new DElGetoFolder(GetInboxFolders));
            }
            else
            {
                return outlookapp.Session.GetDefaultFolder(Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderInbox).Folders;
            }
        }

        private void GetAllSubFoldersRecurse(Folder RootFolder, List<Folder> FolderList)
        {
            foreach (Folder childfolder in RootFolder.Folders)
            {
                FolderList.Add(childfolder);
                GetAllSubFoldersRecurse(childfolder, FolderList);
            }
        }

        private List<Folder> GetAllSubFolders(Folder RootFolder)
        {
            List<Folder> ReturnList = new List<Folder>();
            ReturnList.Add(RootFolder);
            GetAllSubFoldersRecurse(RootFolder, ReturnList);
            return ReturnList;
        }

        private void GenerateStatistics()
        {
            //OK now, some thoughts about the reputation system
            //First, the ratio received/sent is important
            //Second we could do some correlation based on social media
            foreach (MAPIFolder folder in outlookapp.Session.Folders)
            {
                foreach (MailItem mi in GetAllItemsRecursion(folder, new List<MailItem>()))
                {
                    try
                    {
                        if (!(mi.SenderEmailAddress.ToLowerInvariant().Equals(mi.Session.CurrentUser.Address.ToLowerInvariant())))
                        {
                            //We have received the mail
                            Contact TempContact = new Contact(mi);
                            if (!FromToMessages.ContainsKey(TempContact))
                            {
                                List<string> Tempmessage = new List<string>();
                                ContactMessages TempMessages = new ContactMessages(new List<ContactMessage> { new ContactMessage(mi.EntryID, mi.SentOn) }, new List<ContactMessage>());
                                TempMessages.LastMessage = mi.SentOn;
                                TempMessages.LastMessageReceived = mi.SentOn;
                                FromToMessages.Add(TempContact, TempMessages);
                            }
                            else
                            {
                                if (FromToMessages[TempContact].LastMessage < mi.SentOn)
                                {
                                    FromToMessages[TempContact].LastMessage = mi.SentOn;
                                }
                                if (FromToMessages[TempContact].LastMessageReceived < mi.SentOn)
                                {
                                    FromToMessages[TempContact].LastMessageReceived = mi.SentOn;
                                }
                                FromToMessages[TempContact].FromMessages.Add(new ContactMessage(mi.EntryID, mi.SentOn));
                            }

                            Contact retrievedContact = FromToMessages.Keys.Single(x => x.Equals(TempContact));
                            foreach (Recipient item in mi.Recipients)
                            {
                                Contact TempConnectedContact = new Contact(item);
                                if (retrievedContact != TempConnectedContact)
                                {
                                    if (!retrievedContact.ConnectedContacts.Contains(TempConnectedContact))
                                    {
                                        retrievedContact.ConnectedContacts.Add(TempConnectedContact);
                                    }
                                }
                            }
                        }
                        else
                        {
                            //We have sent the mail

                            foreach (Recipient recipient in mi.Recipients)
                            {
                                Contact TempContact = new Contact(recipient);
                                if (!FromToMessages.ContainsKey(TempContact))
                                {
                                    List<string> Tempmessage = new List<string>();
                                    ContactMessages TempMessages = new ContactMessages(new List<ContactMessage>(), new List<ContactMessage> { new ContactMessage(mi.EntryID, mi.SentOn) });
                                    TempMessages.LastMessage = mi.SentOn;
                                    TempMessages.LastMessageSent = mi.SentOn;
                                    FromToMessages.Add(TempContact, TempMessages);
                                }
                                else
                                {
                                    if (FromToMessages[TempContact].LastMessage < mi.SentOn)
                                    {
                                        FromToMessages[TempContact].LastMessage = mi.SentOn;
                                    }
                                    if (FromToMessages[TempContact].LastMessageSent < mi.SentOn)
                                    {
                                        FromToMessages[TempContact].LastMessageSent = mi.SentOn;
                                    }
                                    FromToMessages[TempContact].ToMessages.Add(new ContactMessage(mi.EntryID, mi.SentOn));
                                }

                                Contact retrievedContact = FromToMessages.Keys.Single(x => x.Equals(TempContact));

                                Contact SenderContact = new Contact(mi);
                                if (SenderContact != retrievedContact)
                                {
                                    if (!retrievedContact.ConnectedContacts.Contains(SenderContact))
                                    {
                                        retrievedContact.ConnectedContacts.Add(SenderContact);
                                    }
                                }

                                foreach (Recipient receiver in mi.Recipients)
                                {
                                    if (receiver != recipient)
                                    {
                                        Contact TempConnectedContact = new Contact(receiver);
                                        if (!retrievedContact.ConnectedContacts.Contains(TempConnectedContact))
                                        {
                                            retrievedContact.ConnectedContacts.Add(TempConnectedContact);
                                        }
                                    }
                                }
                            }
                        }
                    }
                    catch (Exception)
                    {
                    }
                }
            }

            foreach (var item in outlookapp.Session.GetDefaultFolder(OlDefaultFolders.olFolderContacts).Items)
            {
                try
                {
                    ContactItem contact = item as ContactItem;

                    if (contact.Email1Address != null)
                    {
                        try
                        {
                            Contact TempContact1 = new Contact(contact.Email1Address);
                            Contact retrievedContact1 = FromToMessages.Keys.Single(x => x.Equals(TempContact1));
                            if (retrievedContact1 != null)
                            {
                                retrievedContact1.OutlookContact = contact.EntryID;
                            }
                        }
                        catch (Exception)
                        {
                        }

                    }

                    if (contact.Email2Address != null)
                    {
                        try
                        {
                            Contact TempContact2 = new Contact(contact.Email2Address);
                            Contact retrievedContact2 = FromToMessages.Keys.Single(x => x.Equals(TempContact2));
                            if (retrievedContact2 != null)
                            {
                                retrievedContact2.OutlookContact = contact.EntryID;
                            }
                        }
                        catch (Exception)
                        {
                        }

                    }

                    if (contact.Email3Address != null)
                    {
                        try
                        {
                            Contact TempContact3 = new Contact(contact.Email3Address);
                            Contact retrievedContact3 = FromToMessages.Keys.Single(x => x.Equals(TempContact3));
                            if (retrievedContact3 != null)
                            {
                                retrievedContact3.OutlookContact = contact.EntryID;
                            }
                        }
                        catch (Exception)
                        {

                        }
                    }
                }
                catch (Exception)
                {
                }
            }

            //Items SentItems = GetSentItems();
            //foreach (object Item in SentItems)
            //{
            //    try
            //    {
            //        MailItem mi = Item as MailItem;

            //        Contact TempContact = new Contact(mi.Recipients

            //        if (!FromMessages.ContainsKey(TempContact))
            //        {
            //            Reputation.Add(TempContact, 1);

            //            //List<string> Tempmessage = new List<string>();
            //            //FromMessages.Add(TempContact, new List<string> { mi.EntryID });
            //        }
            //        else
            //        {
            //            Reputation[TempContact] = Reputation[TempContact] + 1;
            //            //FromMessages[TempContact].Add(mi.EntryID);
            //        }
            //    }
            //    catch (Exception)
            //    {
            //    }
            //}

            foreach (var item in FromToMessages)
            {
                item.Key.LastConversationDateTime = item.Value.LastMessage;
                item.Key.LastMessageReceived = item.Value.LastMessageReceived;
                item.Key.LastMessageSent = item.Value.LastMessageSent;
            }


            Stream stream = File.Open(fileName, FileMode.Create);
            BinaryFormatter bFormatter = new BinaryFormatter();
            bFormatter.Serialize(stream, FromToMessages);
            stream.Close();
        }

        private void ContactAction()
        {
            Contact ActionedContact = (Contact)listBox1.SelectedItem;
            if (ActionedContact.UnreadMails)
            {
                foreach (MailItem unreadmail in ActionedContact.UnreadMailsList)
                {
                    unreadmail.Display(false);
                }
                ActionedContact.UnreadMailsList = null;
                ActionedContact.UnreadMails = false;
                RefreshList();
            }
            else
            {
                MailItem message = (MailItem)outlookapp.CreateItem(OlItemType.olMailItem);
                message.Recipients.Add(ActionedContact.ContactString);
                message.Recipients.ResolveAll();
                message.Display(false);
            }
        }

        private void openToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ContactAction();
        }

        private void viewHistoryToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SNAIL.Contact c = new SNAIL.Contact(((Contact)listBox1.SelectedItem), outlookapp, FromToMessages[(Contact)listBox1.SelectedItem]);
            c.Show();
        }

        private void showContactToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (((Contact)listBox1.SelectedItem).OutlookContact == null)
            {
                ContactItem newcontact = (ContactItem)outlookapp.CreateItem(OlItemType.olContactItem);

                newcontact.FullName = ((Contact)listBox1.SelectedItem).DisplayString;
                newcontact.Email1Address = ((Contact)listBox1.SelectedItem).ContactString;
                newcontact.Save();
                ((Contact)listBox1.SelectedItem).OutlookContact = newcontact.EntryID;
                newcontact.Display(false);
            }
            else
            {
                ContactItem contact = (ContactItem)outlookapp.Session.GetItemFromID(((Contact)listBox1.SelectedItem).OutlookContact, null);
                contact.Display(false);
            }
        }

        private void contextMenuStrip1_Opening(object sender, CancelEventArgs e)
        {
            try
            {
                if (((Contact)listBox1.SelectedItem).OutlookContact == null)
                {
                    showContactToolStripMenuItem.Text = "Add to Contacts";
                    //findOnFacebookToolStripMenuItem.Text = "Create from facebook Contact";
                }
                else
                {
                    showContactToolStripMenuItem.Text = "Show Contact";
                    //findOnFacebookToolStripMenuItem.Text = "Associate facebook Contact";
                }

                if (((Contact)listBox1.SelectedItem).FacebookUID == null)
                {
                    findOnFacebookToolStripMenuItem.Text = "Find on facebook";
                }
                else
                {
                    findOnFacebookToolStripMenuItem.Text = "Change facebook user";
                }

                if (((Contact)listBox1.SelectedItem).FacebookUID == null)
                {
                    deleteFacebookBindingToolStripMenuItem.Visible = false;
                }
                else
                {
                    deleteFacebookBindingToolStripMenuItem.Visible = true;
                }
            }
            catch (Exception)
            {
            }
        }

        private void findOnFacebookToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SNAIL.Interfaces.FacebookSelecter newFacebookselecter = new SNAIL.Interfaces.FacebookSelecter(facebookService1.Friends.GetUserObjects());
            newFacebookselecter.ShowDialog();
            ((Contact)listBox1.SelectedItem).FacebookUID = newFacebookselecter.UserID;
            if (((Contact)listBox1.SelectedItem).FacebookUID != null)
            {
                try
                {
                    ((Contact)listBox1.SelectedItem).ContactImagePath = facebookService1.Users.GetInfo(((Contact)listBox1.SelectedItem).FacebookUID.Value).pic;
                }
                catch (Exception)
                {
                }
            }
            RefreshList();
        }

        private void deleteFacebookBindingToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ((Contact)listBox1.SelectedItem).FacebookUID = null;
            ((Contact)listBox1.SelectedItem).ContactImagePath = null;
            RefreshList();
        }
    }
}